﻿using Communication;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace nblTool.utils
{
    /// <summary>
    /// 自定义串口消息接收事件委托
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    //public delegate void ReceiveDataEventHandler(object sender, ReceiveDataEventArg e);
    
    class SerialPortHelper
    {
        public static byte[] bytes;
        private static SerialPortHelper instance = new SerialPortHelper();
        /// <summary>
        /// 自定义串口消息接收事件
        /// </summary>
        public event EventHandler ReceiveDataEvent;

        //串口字段
        private static SerialPort serialPort = new SerialPort();

        //public static bool isComplete = true;
        //监听串口线程
        static Thread dataReceiveThread;
        /// <summary>
        /// 构造函数
        /// </summary>
        private SerialPortHelper()
        {
            
            
        }
        public static SerialPortHelper Instance
        {
            get { return instance; }
        }

       
        public string serialPortName { 
            get 
            {
                return serialPort.PortName;
            }
        }
        /// <summary>
        /// 串口状态
        /// </summary>
        public bool Status { get => serialPort.IsOpen; }

        /// <summary>
        /// 获取当前计算机所有的串行端口名
        /// </summary>
        /// <returns></returns>
        public static string[] GetPortArray()
        {
            return SerialPort.GetPortNames();
        }

        /// <summary>
        /// 串口参数
        /// </summary>
        public void SetSerialPort(string portName, int baudrate, Parity parity, int databits, StopBits stopBits)
        {
            //端口名
            serialPort.PortName = portName;

            //波特率
            serialPort.BaudRate = baudrate;

            //奇偶校验
            serialPort.Parity = parity;

            //数据位
            serialPort.DataBits = databits;

            //停止位
            serialPort.StopBits = stopBits;

            //串口接收数据事件
            //serialPort.DataReceived += ReceiveDataMethod;
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            //打开串口
            try 
            { 
                serialPort.Open(); 
            } 
            catch (Exception e)
            {
                
            }
            
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        public void Close()
        {
            serialPort.Close();
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data">要发送的数据</param>
        public void SendDataMethod(byte[] data)
        {
            //获取串口状态，true为已打开，false为未打开
            bool isOpen = serialPort.IsOpen;

            if (!isOpen)
            {
                Open();
            }
            //isComplete = false;
            //发送字节数组
            //参数1：包含要写入端口的数据的字节数组。
            //参数2：参数中从零开始的字节偏移量，从此处开始将字节复制到端口。
            //参数3：要写入的字节数。 
            serialPort.Write(data, 0, data.Length);
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data">要发送的数据</param>
        public void SendDataMethod(string data)
        {
            //获取串口状态，true为已打开，false为未打开
            bool isOpen = serialPort.IsOpen;

            if (!isOpen)
            {
                Open();
            }

            //直接发送字符串
            serialPort.Write(data);
        }

        /// <summary>
        /// 串口接收到数据触发此方法进行数据读取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ReceiveDataMethod(object sender, SerialDataReceivedEventArgs e)
        {
            ReceiveDataEventArg arg = new ReceiveDataEventArg();

            //读取串口缓冲区的字节数据
            //arg.Data = new byte[serialPort.BytesToRead];
            arg.Data = new byte[serialPort.BytesToRead];
            serialPort.Read(arg.Data, 0, serialPort.BytesToRead);
            string msgStr = "";
            for (int i = 0; i < arg.Data.Length; i++)
            {
                msgStr += arg.Data[i].ToString("X2") + " ";
            }
            bytes=ByteUtils.addBytes(bytes,arg.Data);
            Console.WriteLine(msgStr);
            //SendParamToFrame("接收帧" + DateTime.Now.ToString() + ":" + msgStr);
            //触发自定义消息接收事件，把串口数据发送出去
            if (ReceiveDataEvent != null && AnalysisMessage.GetValidFrameByte(bytes) != null)
            {
                
                arg.Data = AnalysisMessage.GetValidFrameByte(bytes);
                arg.Data = ByteUtils.byteTrimEnd(arg.Data);
                
                bytes = null;
                ReceiveDataEvent.Invoke(null, arg);
            }
        }

        public void dataReceive()
        {
            try
            {
                //串口数据解析方法(忽视第二个参数，根据自己的解析方式自己写，这里放一个公司的串口解析)
                byte[] b = null;
                dataReceiveThread = new Thread(() => {
                    int j = 0;
                    //DataReceiveFunction(ref j);
                    int i = 0;

                });
                if (dataReceiveThread != null && dataReceiveThread.IsAlive)
                {
                    //result = b;
                    dataReceiveThread.Abort();
                }
                dataReceiveThread.Start();
            }
            catch (Exception ex)
            {
                //UIMessageBox.ShowError(ex.Message);
            }

        }
        

        public bool DataReceiveFunction()
        {
            try
            {
                /** **/
                byte[] RxBuffer = new byte[1000];
                UInt16 usRxLength = 0;

                //int index = 0;//用于记录此时的数据次序
                byte[] byteTemp = new byte[1000];
                ReceiveDataEventArg arg = new ReceiveDataEventArg();
                serialPort.ReadTimeout=3000;
                while (true)
                {
                    
                    if (serialPort != null && serialPort.IsOpen)
                    {
                        try
                        {
                            try
                            {
                                UInt16 usLength = 0;
                                try
                                {

                                    usLength = (UInt16)serialPort.Read(RxBuffer, usRxLength, 700);
                                }
                                catch (Exception err)
                                {
                                    
                                    return false;
                                }

                                
                                usRxLength += usLength;
                                //byte[] recvByte = ByteUtils.byteTrimEnd(RxBuffer);
                                byte[] recvByte = AnalysisMessage.GetValidFrameByte(RxBuffer);
                                
                                if (recvByte != null)
                                {
                                    //byte[] recvByte = ByteUtils.byteTrimEnd(RxBuffer);
                                    arg.Data = ByteUtils.byteTrimEnd(recvByte); ;
                                    //arg.Data = recvByte;
                                    ReceiveDataEvent.Invoke(null, arg);
                                    //break;
                                    return true;
                                }
                                
                                
                                Thread.Sleep(10);
                            }
                            finally
                            {

                            }
                        }
                        catch (Exception ex)
                        {
                            //MessageBox.Show(ex.Message);
                        }
                    }

                    Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);

                return false;
            }
            
        }

        public override string ToString()
        {
            return serialPort.PortName + "|" + serialPort.BaudRate.ToString() + "|" + 
                serialPort.DataBits.ToString()+"|"+serialPort.Parity.ToString()+"|"+serialPort.StopBits.ToString();
        }
    }
    
    /// <summary>
    /// 串口接收数据事件的参数
    /// </summary>
    public class ReceiveDataEventArg : EventArgs
    {
        /// <summary>
        /// 串口接收到的数据
        /// </summary>
        public byte[] Data { get; set; }
    }

}
